﻿(function ($, undefined) {
    var instances = {};
    var instanceTemplate = {
        selector: '',
        pages: [],
        tagStack: [],
        currentPageIndex: 0
    };

    var getInstance = function (selector) {
        var mSelector = $(selector).selector;
        return instances[mSelector] ? instances[mSelector] :
            (function () {
                var instance = $.extend({}, instanceTemplate);
                instance.selector = mSelector;
                instance.width = $(selector).width();
                instance.height = $(selector).height();
                instances[mSelector] = instance;

                return instance;
            })();
    };

    var getTempPage = function (i, width, selector) {
        if (!i) i = 0;
        if (!width || width < 200) width = 200;
        var tempPageContainer = $('#reader-temp');
        if (tempPageContainer.length == 0) {
            tempPageContainer = $('<div id="reader-temp"></div>')
                .appendTo(selector && $(selector).parent() ? $(selector).parent() : $('body'))
                .css({
                    'position': 'absolute',
                    'top': '0',
                    'left': '-80000px',
                    'width': width + 'px',
                    'height': selector && $(selector).parent() ? $(selector).parent().height() + 'px' : '600px',
                    'overflow': 'hidden'
                });
            tempPageContainer.append('<div style="clear:both;"></div>');
        }
        var tempPage = tempPageContainer.find('#reader-temp-' + i);
        if (tempPage.length == 0) {
            tempPageContainer.prepend('<div style="clear:both;"></div>');
            tempPage = $('<div id="reader-temp-' + i + '"></div>')
                .prependTo(tempPageContainer)
                .css({
                    'float': 'left',
                    'width': width + 'px',
                    'height': 'auto'
                });
        }
        tempPage.width(width);
        return tempPage;
    };

    var convertToArray = function (content) {
        var result = [];
        var currentWord = '';
        var isInTag = false;

        for (var index = 0; index < content.length; index++) {
            var currentChar = content[index];

            if (currentChar == ' ') {
                if (isInTag) {
                    currentWord += currentChar;
                } else if (currentWord.length > 0) {
                    result.push(currentWord);

                    currentWord = '';
                }
            } else if (currentChar == '<') {
                if (currentWord.length > 0) {
                    // save the last word
                    result.push(currentWord);
                }
                currentWord = '<';
                isInTag = true;
            } else if (currentChar == '>') {
                if (currentWord.length > 0) {
                    currentWord += currentChar;

                    // save the last word
                    result.push(currentWord);
                    currentWord = '';
                }

                if (isInTag) {
                    isInTag = false;
                }
            } else {
                currentWord += currentChar;
            }
        }

        if (isInTag) {
            currentWord += '>';
        }

        if (currentWord.length > 0) {
            result.push(currentWord);
        }

        return result;
    };

    var pageBag = [];

    var createPage = function (selector) {
        var instance = getInstance(selector);
        var container = $('#reader-pages-container');

        if (container.length == 0) {
            container = $('<div id="reader-pages-container"></div>')
                .appendTo($(selector).parent())
                .css({
                    'position': 'absolute',
                    'top': '0',
                    'left': '-90000px',
                    'width': '200px',
                    'height': '100px',
                    'overflow': 'hidden'
                });
        }

        var element = $(selector);

        var page = element.clone().appendTo(container)
            .attr({
                'id': '',
                'class': ''
            })
            .css({
                'height': 'auto',
                'width': instance.width + 'px'
            });

        pageBag.push(page);

        instance.pages.push(page);

        return page;
    };
        
    var splitElement = function (instance, element, height) {
        if (element.height() <= height) {
            return {
                part1: element,
                part2: null
            };
        } else if (height < 200) {
            return {
                part1: null,
                part2: element
            };
        }
        var part1 = getTempPage(1, instance.width, instance.selector);
        part1.html('');

        var part2 = getTempPage(2, instance.width, instance.selector);
        part2.html(element.html());

        var element1 = part1;
        var element2 = part2;
        var currentElement = null;
        var currentElementCloned = null;
        var heightRemaining = height;
        do {
            var isFirstElement = true;
            do {
                currentElement = element2.contents().first();

                if (currentElement.length > 0) {
                    currentElementCloned = currentElement.clone(true);
                    
                    currentElementCloned.appendTo(element1);
                    if (isFirstElement) {
                        currentElementCloned.css({
                            'margin-top': '0',
                            'padding-top': '0'
                        });
                        isFirstElement = false;
                    }
                    element2.contents().first().remove();
                    if (element1.height() == heightRemaining) {
                        currentElementCloned = null;
                    }
                } else {
                    currentElementCloned = null;
                    break;
                }
            } while (element1.height() < heightRemaining);

            if (currentElementCloned != null) {
                if (currentElementCloned[0].nodeType == 3) {
                    element1.contents().last().remove();
                    var doneWithElement1 = false;
                    var textArray = convertToArray(currentElement.text());
                    while (textArray.length > 0 && !doneWithElement1) {
                        var text = $.trim(textArray.shift());
                        if (text.length > 0) {
                            var valueBefore = element1.html();
                            element1.append(text + ' ');
                            if (element1.height() > heightRemaining) {
                                element1.html(valueBefore);
                                textArray.unshift(text);
                                doneWithElement1 = true;
                            }
                        }
                    }

                    if (textArray.length > 0) {
                        element2.prepend(textArray.join(' '));
                    }

                    currentElementCloned = null;
                    currentElement = null;
                } else if (currentElementCloned.text().trim().length > 0) {
                    currentElement = currentElementCloned.clone();
                    element2.prepend(currentElement);
                    currentElementCloned.html('');
                    if (currentElementCloned && currentElementCloned.length > 0) {
                        currentElementCloned.css({
                            'margin-bottom': '0',
                            'padding-bottom': '0'
                        });
                        if (currentElementCloned.prop("tagName") == 'LI') {
                            currentElementCloned.css('list-style', 'none');
                        }
                    }
                    heightRemaining = heightRemaining - element1.outerHeight();
                    element1 = currentElementCloned;
                    element2 = currentElement;                    
                } else {
                    element1.remove(currentElementCloned);
                    currentElement = null;
                }
            }

            if (heightRemaining <= 0) currentElement = null;
        } while (currentElement != null && currentElement.length > 0);

        return {
            part1: part1,
            part2: part2
        };
    };
    
    $.reader = function (selector) {
        var instance = getInstance(selector);
        return {
            addContent: function (content) {
                var tempPage = getTempPage(0, instance.width, instance.selector);

                tempPage.html(content);

                var itemToSplit = tempPage;
                while (true) {
                    var split = splitElement(instance, itemToSplit, instance.height);
                    if (split.part1 && split.part1.length > 0) {
                        createPage(selector).html(split.part1.html());

                        if (split.part2 && split.part2.length > 0) {
                            itemToSplit = split.part2;
                        } else {
                            break;
                        }
                    } else {
                        break;
                    }
                }
                
            },

            getPage: function (i) {
                if (i >= instance.pages.length) {
                    return null;
                } else {
                    instance.currentPageIndex = i;
                    return instance.pages[i].clone();
                }
            },

            getCurrentPageIndex: function () {
                return (instance && instance.currentPageIndex) ? instance.currentPageIndex : 0;
            },

            getPageCount: function () {
                return (instance && instance.pages) ? instance.pages.length : 0;
            }
        };
    };
    $(document).ready(function () {
        var readerArea = $('#content-area');
        if (readerArea.length > 0) {
            var content = readerArea.html();
            readerArea.html('');
            var reader = $.reader('#content-area');
            reader.addContent(content);

            var firstPage = reader.getPage(0);
            if (firstPage != null && firstPage.length > 0) {
                readerArea.html(firstPage.html());
            }

            // navigation
            var container = $('#nineseas-reader-content');
            if (container.length == 0) return;

            // previous button
            var previousButton = container.find('#previousPage');
            if (reader.getPageCount() > 1) {                
                if (previousButton.length == 0) {
                    previousButton = $('<a href="javascript:;" id="previousPage" class="book-page-navigation"></a>')
                            .prependTo(container)
                            .html('<div><div class="icon-direction"></div></div>');
                } else {
                    var href = previousButton.attr('href');
                    if (href && href.length > 0) {
                        previousButton.attr('href', 'javascript:;')
                            .attr('back', href);
                    }
                }
                previousButton.click(function () {
                    var currentPageIndex = reader.getCurrentPageIndex();
                    if (currentPageIndex > 0) {
                        currentPageIndex--;
                        readerArea.html(reader.getPage(currentPageIndex));

                        if (currentPageIndex == 0 && (!previousButton.attr('back') || previousButton.attr('back').length == 0)) {
                            previousButton.hide();
                        }

                        if (container.find('#nextPage').length > 0) {
                            container.find('#nextPage').show();
                        }

                        readerArea.trigger("pageChanged");
                        
                    } else {
                        var href = previousButton.attr('back');
                        if (href && href.length > 0) {
                            window.location.href = href;
                        }
                    }
                });
            }

            // next button
            var nextButton = container.find('#nextPage');
            if (reader.getPageCount() > 1) {
                if (nextButton.length == 0) {
                    nextButton = $('<a href="javascript:;" id="nextPage" class="book-page-navigation"></a>')
                            .prependTo(container)
                            .html('<div><div class="icon-direction"></div></div>');
                } else {
                    var href = nextButton.attr('href');
                    if (href && href.length > 0) {
                        nextButton.attr('href', 'javascript:;')
                            .attr('next', href);
                    }
                }
                nextButton.click(function () {
                    var currentPageIndex = reader.getCurrentPageIndex();
                    if (currentPageIndex < reader.getPageCount() - 1) {
                        currentPageIndex++;
                        readerArea.html(reader.getPage(currentPageIndex));

                        if ((currentPageIndex == reader.getPageCount() - 1)
                                && (!nextButton.attr('next') || nextButton.attr('next').length == 0)) {
                            nextButton.hide();
                        }
                        
                        if (container.find('#previousPage').length > 0) {
                            container.find('#previousPage').show();
                        }

                        readerArea.trigger("pageChanged");
                    } else {
                        var href = nextButton.attr('next');
                        if (href && href.length > 0) {
                            window.location.href = href;
                        }
                    }
                });
            }

            var paging = $(".books-paging");
            if (paging.length > 0 && reader.getPageCount() > 1) {
                var currentPage = $("<span class='pager-current'></span>")
                    .appendTo(paging)
                    .html(reader.getCurrentPageIndex() + 1);

                var totalPages = $("<span class='total-pages'></span>")
                    .appendTo(paging)
                    .html("/ " + reader.getPageCount());

                var ul = $("<ul></ul>")
                    .appendTo(paging);

                for (var i = 0; i < reader.getPageCount() ; i++) {
                    var li = $("<li></li>")
                        .appendTo(ul);
                    var thisPageIndex = i;
                    var label = "" + (thisPageIndex + 1);
                    var a = $("<a></a>")
                        .appendTo(li)
                        .attr("index", i)
                        .attr("href", "javascript:;")
                        .html(label);
                }

                $(".books-paging ul a").on("click", function (e) {
                    var $this = $(this);
                    var index = parseInt($this.attr("index"));
                    readerArea.html(reader.getPage(index));

                    currentPage.html($this.html());

                    readerArea.trigger("pageChanged");
                });

                readerArea.on("pageChanged", function () {
                    currentPage.html(reader.getCurrentPageIndex() + 1);
                });

                $.popupPanel(".books-paging .pager-current, .books-paging .total-pages", ".books-paging ul");
            }
        }
    });
})(jQuery);